//
// Created by Administrator on 2021/5/22.
// @file simple_operation.cpp
// @author jmdvirus
// @date $YEAR-$MONTH-22 12:56:09
//

#include <stdio.h>

#include "simple_operation.h"

int SimpleOperation::Run(int argc, char **args)
{
    printf("run\n");
    char *file = args[1];
    cv::Mat img = cv::imread(file);
    printf("filename [%s], image size [%d,%d]\n", file,img.cols, img.rows);

    TestUnknow(img);
//    TestOneImage(img);
//    TestBig(img);
//    TestErode(img);
//    TestRevert(img);
//    TestEquist(img);
//    TestDetect(img);
//    TestImageHSV(img);
//    TestGrabImage(img);
//    TestWaveImg(img);
//    TestRemoveLight(img);
    return 0;
}

int SimpleOperation::TestUnknow(cv::Mat &img)
{
    cv::Mat result;
    cv::Laplacian(img, result, CV_32F, 7);
    SaveImage(result, "so.jpg");
    return 0;
}

int SimpleOperation::TestOneImage(cv::Mat &img)
{
    cv::cvtColor(img, img, cv::COLOR_BGR2GRAY);
    std::vector<std::vector<cv::Point>> contours;
    cv::findContours(img, contours, cv::RETR_TREE, cv::CHAIN_APPROX_SIMPLE);
    SaveImage(img, "so.jpg");

    cv::Mat rr(img.size(), CV_8U, cv::Scalar(255));
    printf("counts [%u]\n", contours.size());
    cv::drawContours(rr, contours, -1, 0, 2);
    SaveImage(rr, "so1.jpg");
    return 0;
    cv::Mat result;

//    cv::Sobel(img, result, CV_8U, 1, 1, 3, 0.4, 128);
    cv::Laplacian(img, result, CV_32F, 7);
    SaveImage(result, "so1.jpg");
    return 0;
//    result = img;
    cv::threshold(img, result, 100, 200, cv::THRESH_BINARY_INV);
    for (int i = 0; i < 2; i++)
    {
        for (int j = 0; j < result.cols; j++)
        {
//            cv::Vec3b bgr = result.at<cv::Vec3b>(i, j);
//            printf("[%d, %d, %d]", bgr[0], bgr[1], bgr[2]);
            printf("%02d ", int(result.at<uchar>(i,j)));
        }
        printf("\n");
    }
    return 0;
}

int SimpleOperation::TestBig(cv::Mat &img)
{
    cv::Mat result;
//    cv::pyrDown(img, result);
//    cv::pyrUp(img, result);
    cv::resize(img, result, cv::Size(img.cols/4, img.rows/4));
    SaveImage(result, "so.jpg");
    return 0;
}

int SimpleOperation::TestErode(cv::Mat &img)
{
    cv::Mat result;
#if 0
    cv::dilate(img, result, cv::Mat());
    cv::erode(result, result, cv::Mat());
    SaveImage(result, "so.jpg");
#else
    cv::Mat element(5,5,CV_8U, cv::Scalar(1));
    cv::Mat closed;
    cv::morphologyEx(img, closed, cv::MORPH_GRADIENT, cv::Mat());
    SaveImage(closed, "so.jpg");
#endif
    return 0;
}

int SimpleOperation::TestRevert(cv::Mat &img)
{
    cv::Mat lookup(1, 256, CV_8U);
    int div = 64;
    for (int i = 0; i < 256; i++)
    {
        lookup.at<uchar>(i) = 255-i;
//        lookup.at<uchar>(i) = i / div * div + div/2;
    }
    cv::Mat result;
    cv::LUT(img, lookup, result);
    SaveImage(result, "so.jpg");
    return 0;
}

int SimpleOperation::TestEquist(cv::Mat &img)
{
    cv::Mat result;
    cv::Mat gray;
    cv::cvtColor(img, gray, cv::COLOR_BGR2GRAY);
    cv::equalizeHist(gray, result);
    SaveImage(result, "so.jpg");
    return 0;
}

void SimpleOperation::TestDetect(const cv::Mat &img)
{
    cv::Mat mask;
    simpleFunction.DetectHSColor(img, 160, 10, 25, 166, mask);

    cv::Mat detected(img.size(), CV_8UC3, cv::Scalar(0, 0, 0));
    img.copyTo(detected, mask);
    SaveImage(detected, "so.jpg");
}

int SimpleOperation::TestImageHSV(cv::Mat &img)
{
    cv::Mat hsv;
    cv::cvtColor(img, hsv, cv::COLOR_BGR2HSV);
    std::vector<cv::Mat> channels;
    cv::split(hsv, channels);
    cv::Mat result;
    channels[0] = 215;
    cv::merge(channels, hsv);
    cv::cvtColor(hsv, result, cv::COLOR_HSV2BGR);
    SaveImage(result, "so.jpg");
    return 0;
}

int SimpleOperation::TestGrabImage(cv::Mat &img)
{
    cv::Mat result;
    cv::Mat bgModel, fgModel;
    cv::Rect rectangle(500, 200, 2000, 1400);
    cv::grabCut(img, result, rectangle, bgModel, fgModel, 5, cv::GC_INIT_WITH_RECT);
    cv::compare(result, cv::GC_PR_FGD, result, cv::CMP_EQ);
    cv::Mat foreground(img.size(), CV_8UC3, cv::Scalar(255,255,255));
//    img.copyTo(foreground, result);
    SaveImage(fgModel, "so.jpg");
    return 0;
}

cv::Mat SimpleOperation::WaveImg(cv::Mat &img)
{
    cv::Mat srcX(img.rows, img.cols, CV_32F);
    cv::Mat srcY(img.rows, img.cols, CV_32F);

    for (int i = 0; i < img.rows; i++)
    {
        for (int j = 0; j < img.cols; j++)
        {
            srcX.at<float>(i, j) = j;
            srcY.at<float>(i, j) = img.rows - i - 1;
//            srcX.at<float>(i,j) = j;
//            srcY.at<float>(i,j) = i + 5 * sin(j/10.0);
        }
    }

    cv::Mat result;
    cv::remap(img, result, srcX, srcY, cv::INTER_LINEAR);
    SaveImage(result, "so.jpg");
    return cv::Mat();
}

int SimpleOperation::TestWaveImg(cv::Mat &img)
{
    WaveImg(img);
    return 0;
}

int SimpleOperation::TestRemoveLight(cv::Mat &img)
{
    cv::Mat pattern = CalculateLightPattern(img);
    cv::Mat ret = RemoveLight(img, pattern, 1);
    SaveImage(ret, "so.jpg");
    return 0;
}

cv::Mat SimpleOperation::RemoveLight(cv::Mat &img, cv::Mat pattern, int method)
{
    cv::Mat aux;
    if (method == 1)
    {
        cv::Mat img32, pattern32;
        img.convertTo(img32, CV_32F);
        pattern.convertTo(pattern32, CV_32F);
        aux = 1 - (img32/pattern32);
        aux.convertTo(aux, CV_8U, 255);
    }
    else
    {
        aux = pattern - img;
    }
    return aux;
}

cv::Mat SimpleOperation::CalculateLightPattern(cv::Mat &img)
{
    cv::Mat pattern;
    cv::blur(img, pattern, cv::Size(img.cols/3, img.cols/3));
    return pattern;
}
